﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using CI.Interfaces;

namespace CI.Organism
{
    /// <summary>The chromosone collection</summary>
    [CollectionDataContract]
    public class ChromosomeCollection : List<IChromosome>, IChromosomeCollection
    {
        /// <summary>
        /// Take this parents Chromosomes and create a new Chromosomes collection to be put in the new Organism
        /// Mutate the current Chromosomes and return a new one, deep class level mutation
        /// </summary>
        /// <param name="mutationRate">mutation rate to be applied</param>
        /// <param name="childOrganism">child Organism it will be going into</param>
        /// <returns>new chromosomes for child</returns>
        public IChromosomeCollection Mutate(double mutationRate, IOrganism childOrganism)
        {
            // create the new chromosome collection
            var childChromosomes = new ChromosomeCollection();

            // currently just mutate the existing ones(copy)
            foreach (var chromsome in this)
            {
                childChromosomes.Add(chromsome.Mutate(mutationRate, childOrganism));
            }

            // mutate making new ones(new)
            if (Mutation.MutateState(mutationRate))
            {
                // create a new chromosome with empty genes
                IChromosome chromsome = new Chromosome(Guid.NewGuid()) { Genes = new GeneCollection() };
                // add a mutated chromosome to the collection
                childChromosomes.Add(chromsome.Mutate(mutationRate, childOrganism));
            }

            // mutate removing some genes(delete)
            if (Mutation.MutateState(mutationRate) && (childChromosomes.Count > 0))
            {
                childChromosomes.RemoveRange(Mutation.CollectionSelect(childChromosomes), 1);
            }

            return childChromosomes;
        }

        /// <summary>
        /// Find the Chromosone with the specifed guid
        /// </summary>
        /// <param name="guid">guid to find</param>
        /// <returns>Chromosone</returns>
        public IChromosome Find(Guid guid)
        {
            return FindLast(chromsome => chromsome.Guid == guid);
        }
    }
}